package com.ggy.tuibi.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.sun.net.httpserver.HttpPrincipal;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.ChallengeState;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

@Component
@Slf4j
public class DoRequestUtils {
    public String request(Method method, String url, String body, Map<String, Object> params) {
        switch (method) {
            case POST:
                return doPost2(url, body, params);
            case GET:
//                return doGet(url, params);
            default:
                throw new RuntimeException("请求参数异常");
        }
    }


    public static HttpResponse doPost(String url, String body, Map<String, Object> params) {
        if (CollUtil.isNotEmpty(params)) {
            StringBuffer stringBuffer = new StringBuffer(url);
            params.forEach((key, value) -> {
                if (stringBuffer.toString().contains("?")) {
                    stringBuffer.append("&").append(key).append("=").append(value);
                } else {
                    stringBuffer.append("?").append(key).append("=").append(value);
                }
            });
            url = stringBuffer.toString();
        }
        HttpRequest request = HttpUtil.createPost(url);
        Proxy proxy = getProxy();
        request.setProxy(proxy);
        if (StrUtil.isNotBlank(body)) {
            request.body(body);
        }
        return request.execute();
    }

    public static HttpResponse doGet(String url, Map<String, Object> params) {
        if (CollUtil.isNotEmpty(params)) {
            StringBuffer stringBuffer = new StringBuffer(url);
            params.forEach((key, value) -> {
                if (stringBuffer.toString().contains("?")) {
                    stringBuffer.append("&").append(key).append("=").append(value);
                } else {
                    stringBuffer.append("?").append(key).append("=").append(value);
                }
            });
            url = stringBuffer.toString();
        }
        Proxy proxy = getProxy();
        return HttpUtil.createGet(url).setProxy(proxy).execute();
    }

    public static Proxy getProxy() {
        HttpResponse response = HttpUtil.createGet("https://share.proxy.qg.net/get?key=I3NPJEDG&num=1&area_ex=420100&isp=0&format=json&distinct=false").execute();
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        log.info("获取代理:{}", response.body());
        if ("SUCCESS".equals(jsonObject.getStr("code"))) {
            String service = jsonObject.getJSONArray("data").getJSONObject(0).getStr("server");
            String[] serviceSplit = service.split(StrUtil.COLON);
            InetSocketAddress socketAddress = new InetSocketAddress(serviceSplit[0], Integer.parseInt(serviceSplit[1]));
            return new Proxy(Proxy.Type.HTTP, socketAddress);
        }
        throw new RuntimeException("获取代理失败");
    }

    public static HttpHost getHttpHost() {
        HttpResponse response = HttpUtil.createGet("https://share.proxy.qg.net/get?key=I3NPJEDG&num=1&area_ex=420100&isp=0&format=json&distinct=false").execute();
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        log.info("获取代理:{}", response.body());
        if ("SUCCESS".equals(jsonObject.getStr("code"))) {
            String service = jsonObject.getJSONArray("data").getJSONObject(0).getStr("server");
            String[] serviceSplit = service.split(StrUtil.COLON);
            return new HttpHost(serviceSplit[0], Integer.parseInt(serviceSplit[1]), "http");
        }
        throw new RuntimeException("获取代理失败");
    }

    final static String proxyUser = "I3NPJEDG";
    final static String proxyPass = "E47DE6563682";
    private static PoolingHttpClientConnectionManager cm = null;
    private static HttpRequestRetryHandler httpRequestRetryHandler = null;
    private static HttpHost httpHost = null;
    private static CredentialsProvider credsProvider = null;
    private static RequestConfig reqConfig = null;

    static {
        ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
        LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
        Registry registry = RegistryBuilder.create()
                .register("http", plainsf)
                .register("https", sslsf)
                .build();
        cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(10);
        cm.setDefaultMaxPerRoute(5);
        credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUser, proxyPass));

    }

    public static String doRequest(HttpRequestBase httpReq) {
        CloseableHttpResponse httpResp = null;
        try {
            httpReq.setConfig(reqConfig);
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setConnectionManager(cm)
                    .setDefaultCredentialsProvider(credsProvider)
                    .build();
            AuthCache authCache = new BasicAuthCache();
            authCache.put(httpHost, new BasicScheme());
            authCache.put(httpHost, new BasicScheme(ChallengeState.PROXY));
            HttpClientContext localContext = HttpClientContext.create();
            localContext.setAuthCache(authCache);
            httpResp = httpClient.execute(httpReq, localContext);
            BufferedReader rd = new BufferedReader(new InputStreamReader(httpResp.getEntity().getContent()));
            StringBuffer stringBuffer = new StringBuffer();
            String line = "";
            while ((line = rd.readLine()) != null) {
                System.out.println(line);
                stringBuffer.append(line);
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (httpResp != null) {
                    httpResp.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        doPost2("http://123.207.202.18:8080/find/post/ip", null, null);
    }

    public static String doPost2(String url, String body, Map<String, Object> params) {
        HttpPost httpPost = new HttpPost(url);
        httpHost = getHttpHost();
        reqConfig = RequestConfig.custom()
                .setExpectContinueEnabled(false)
                .setProxy(httpHost)
                .build();
        return doRequest(httpPost);
    }
}
